package com.truth.lock.configure.redisson;

import com.truth.lock.configure.TruthLockProperties;
import com.truth.lock.exception.RedissonTypeException;
import com.truth.lock.executor.redisson.*;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.*;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author truth
 */
@Configuration
@EnableConfigurationProperties(TruthLockProperties.class)
@ConditionalOnClass(name = {"org.redisson.api.RedissonClient"})
@ConditionalOnProperty(prefix = "truth.lock", name = "lock-type", havingValue = "redisson")
public class RedissonAutoConfiguration {

    @Bean
    public RedissonClient redissonClient(TruthLockProperties properties) {
        RedissonProperties redissonProperties = properties.getRedisson();
        Config config = new Config();
        switch (redissonProperties.getType()) {
            case SINGLE:
                SingleServerConfig singleServerConfig = config.useSingleServer();
                BeanUtils.copyProperties(redissonProperties.getSingle(), singleServerConfig);
                break;
            case SENTINEL:
                SentinelServersConfig sentinelServers = config.useSentinelServers();
                BeanUtils.copyProperties(redissonProperties.getSentinel(), sentinelServers);
                break;
            case MASTER__SLAVE:
                MasterSlaveServersConfig masterSlaveServers = config.useMasterSlaveServers();
                BeanUtils.copyProperties(redissonProperties.getMasterSlave(), masterSlaveServers);
                break;
            case REPLICATE:
                ReplicatedServersConfig replicatedServers = config.useReplicatedServers();
                BeanUtils.copyProperties(redissonProperties.getReplicate(), replicatedServers);
                break;
            default:
                throw new RedissonTypeException("truth.lock.redisson.type must in [SINGLE, SENTINEL, MASTER__SLAVE, REPLICATE]");
        }
        return Redisson.create(config);
    }


    @Bean
    @ConditionalOnBean(type = {"org.redisson.api.RedissonClient"})
    public RedissonLockExecutor redissonFairLockExecutor(RedissonClient redissonClient) {
        return new RedissonFairLockExecutor(redissonClient);
    }

    @Bean
    @ConditionalOnBean(type = {"org.redisson.api.RedissonClient"})
    public RedissonLockExecutor redissonReadLockExecutor(RedissonClient redissonClient) {
        return new RedissonReadLockExecutor(redissonClient);
    }

    @Bean
    @ConditionalOnBean(type = {"org.redisson.api.RedissonClient"})
    public RedissonLockExecutor redissonReentrantLockExecutor(RedissonClient redissonClient) {
        return new RedissonReentrantLockExecutor(redissonClient);
    }

    @Bean
    @ConditionalOnBean(type = {"org.redisson.api.RedissonClient"})
    public RedissonLockExecutor redissonWriteLockExecutor(RedissonClient redissonClient) {
        return new RedissonWriteLockExecutor(redissonClient);
    }

}
